package edu.ccut.saturn.component;

import java.net.URL;
import java.util.Enumeration;

import org.osgi.framework.Bundle;

import edu.ccut.saturn.component.impl.SaturnParameterContext;

public class SaturnComponent  implements IComponent{
	private static final String LOGGER_KEY_BUNDLE_RUNTIME = SaturnLoggerManager.LOGGER_KEY_COMPONENT_RUNTIME;

	protected static ILogger logger = SaturnLoggerManager.getInstance()
			.getSaturnLogger(LOGGER_KEY_BUNDLE_RUNTIME);

	private String fullKey = null;

	private Bundle bundle;

	public SaturnComponent() {
	}

	public SaturnComponent(String fullKey) {
		this.fullKey = fullKey;
	}

	public void setBundle(Bundle bundle) {
		this.bundle = bundle;
	}

	public void execute(IParameterContext parameterContext) throws Exception {
	}

	public String getComponentFullKey() {
		return this.fullKey;
	}

	public void setComponentFullKey(String fullKey) {
		this.fullKey = fullKey;
	}

	/**
	 * Returns a URL to the specified entry in this bundle. The bundle's
	 * classloader is not used to search for the specified entry. Only the
	 * contents of the bundle is searched for the specified entry. A specified
	 * path of "/" indicates the root of the bundle
	 * 
	 * @param name
	 * @return
	 */
	public URL getResource(String name) {

		if (this.bundle != null) {
			return this.bundle.getEntry(name);
		}
		return null;
	}

	/**
	 * Returns an Enumeration of all the paths (String objects) to entries
	 * within the bundle whose longest sub-path matches the supplied path
	 * argument. The bundle's classloader is not used to search for entries.
	 * Only the contents of the bundle is searched. A specified path of "/"
	 * indicates the root of the bundle. Returned paths indicating subdirectory
	 * paths end with a "/". The returned paths are all relative to the root of
	 * the bundle.
	 * 
	 * @param path
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Enumeration<String> getResourcePaths(String path) {

		if (this.bundle != null) {
			return (Enumeration<String>) this.bundle.getEntryPaths(path);
		}
		return null;
	}

	/**
	 * This method serves to execute a logic component in a component. This
	 * logic component will use the connection from the caller when need to
	 * access a data base. This logic component will be in the exist transaction
	 * scope.
	 * 
	 * @param componentContext :
	 *            the parameterContext of original component
	 * @param logicParameterContext :
	 *            the parameterContext of the logic component to be called in a
	 *            component
	 * @param fullKey :
	 *            the fullKey of the logic component to be called
	 * @throws Exception
	 */
	@Deprecated
	protected void executeLogicSupportsTransaction(
			IParameterContext componentContext,
			IParameterContext logicParameterContext, String fullKey)
			throws Exception {

		IComponent component = this.getComponent(fullKey);

		SaturnParameterContext componentParameterContext = (SaturnParameterContext) componentContext;
		SaturnParameterContext parameterContext = (SaturnParameterContext) logicParameterContext;
		parameterContext.setTransactionType("supports");

		if (componentParameterContext.getDatabaseBroker().hasConnection()
				&& !componentParameterContext.getConnection().getAutoCommit()) {

			parameterContext.setConnection(componentParameterContext
					.getConnection());
		}
		component.execute(parameterContext);
	}

	/**
	 * This method serves to execute a logic component in a component. This
	 * logic component will create a new connection when need to access a data
	 * base. This logic component will be in a new transaction scope.
	 * 
	 * @param componentContext :
	 *            the parameterContext of original component
	 * @param logicParameterContext :
	 *            the parameterContext of the logic component to be called in a
	 *            component
	 * @param fullKey :
	 *            the fullKey of the logic component to be called
	 * @throws Exception
	 */
	@Deprecated
	protected void executeLogicRequireNewTransaction(
			IParameterContext componentContext,
			IParameterContext logicParameterContext, String fullKey)
			throws Exception {

		IComponent component = this.getComponent(fullKey);

		SaturnParameterContext parameterContext = (SaturnParameterContext) logicParameterContext;
		parameterContext.setTransactionType("requireNew");
		component.execute(parameterContext);
	}

	/**
	 * This method serves to execute a component in another component. The
	 * component to be called will use the same connection from the caller.
	 * 
	 * @param componentContext :
	 *            the parameterContext of original component
	 * @param newParameterContext :
	 *            the parameterContext of the component to be called in a
	 *            component
	 * @param fullKey :
	 *            the fullKey of the component to be called
	 * @throws Exception
	 */
	@Deprecated
	protected void executeComponent(IParameterContext componentContext,
			IParameterContext newParameterContext, String fullKey)
			throws Exception {

		IComponent component = this.getComponent(fullKey);

		SaturnParameterContext componentParameterContext = (SaturnParameterContext) componentContext;
		SaturnParameterContext parameterContext = (SaturnParameterContext) newParameterContext;
		parameterContext.setConnection(componentParameterContext
				.getConnection());

		component.execute(parameterContext);
	}
	
	protected IComponent getComponent(String fullKey) throws Exception {
		return ComponentManager.getInstance().getComponent(
				fullKey);
	}

	public void info(String message, Throwable throwable) {
		logger.info(message, throwable);
	}

	public void info(String message) {
		logger.info(message);
	}

	public void debug(String message, Throwable throwable) {
		logger.debug(message, throwable);
	}

	public void debug(String message) {
		logger.debug(message);
	}

	public void error(String message, Throwable throwable) {
		logger.error(message, throwable);
	}

	public void error(String message) {
		logger.error(message);
	}

	public void warn(String message, Throwable throwable) {
		logger.warn(message, throwable);
	}

	public void warn(String message) {
		logger.warn(message);
	}

	public void fatal(String message, Throwable throwable) {
		logger.fatal(message, throwable);
	}

	public void fatal(String message) {
		logger.fatal(message);
	}

	public void setLevel(String level) {
		logger.setLevel(level);
	}

	public String getLevel() {
		return logger.getLevel().toString();
	}

	public static ILogger getLogger() {
		return logger;
	}
}
